package microservice

import (
	"fmt"
	"os"
	"path"
)

type IsNotMicroProjectError struct{}
type LanguageType int

const (
	_UNDEFINE_ LanguageType = iota
	_JAVA_     LanguageType = iota
	_PYTHON_   LanguageType = iota
	_NODEJS_   LanguageType = iota
	_GO_       LanguageType = iota
	_RUST_     LanguageType = iota
)

func (e IsNotMicroProjectError) Error() string {
	return "is not a micro service project\n"
}

// Function PathofMavenProject is parse the submodel of a java project by parsing the "pom.xml" file
func PathofMavenProject(root string) ([]string, error) {
	pathinfo, err := os.Stat(root)
	if err != nil {
		return nil, err
	}
	if !pathinfo.IsDir() {
		return nil, fmt.Errorf("the give path :%s is not a valid path", root)
	}
	pom_struct, err := ParsePomFile(path.Join(root, "pom.xml"))
	if err != nil {
		return nil, err
	}
	if len(pom_struct.Modules) == 0 {
		return nil, IsNotMicroProjectError{}
	}

	return pom_struct.Modules, nil
}

// Function checkSubModule
// @param dir : the dir path of a subdir of the misrcoservice project and,
//
//	@return havedocker: if this dir contain a "Dockrfile"  for the docker build process
//	@return lt: the sub project use which type of the language
func checkSubModule(dir string) (havedocker bool, lt LanguageType) {
	havedocker = false
	lt = _UNDEFINE_
	dir_list, err := os.ReadDir(dir)
	if err != nil {
		return
	}
	for _, entry := range dir_list {
		if entry.IsDir() {
			continue
		}
		switch entry.Name() {
		case "Dockerfile":
			havedocker = true
		case "pom.xml":
			lt = _JAVA_
		case "requirements":
			lt = _PYTHON_
		case "nginx.conf":
			fallthrough
		case "package.json":
			lt = _NODEJS_
		case "go.mod":
			lt = _GO_
		case "Cargo.toml":
			lt = _RUST_
		}
	}
	return
}

var TestFcheckSubModule = checkSubModule
var TestAssertFindPom = assertFindPom
var TestAsserYaml = assertFindYaml
var TestAssertFindDockerfile = assertFindDockerfile

// Function assertFindPom , @para : _sin_path is a dir path which may contain the pom.xml file, the @return string will
func assertFindPom(_sin_path string) (string, bool) {
	filename := path.Join(_sin_path, "pom.xml")
	_, err := os.Stat(filename)
	return filename, !os.IsExist(err)
}

func assertFindDockerfile(_sin_path string) (string, bool) {
	filename := path.Join(_sin_path, "Dockerfile")
	_, err := os.Stat(filename)
	return filename, !os.IsExist(err)
}

func assertFindYaml(_sin_path string) (string, bool) {
	filename := path.Join(_sin_path, "src/main/resources/application.yml")
	_, err := os.Stat(filename)
	return filename, !os.IsExist(err)
}
